/*
 * Copyright (C) 2010 SHARP Corporation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package jp.co.sharp.android.decome;

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.os.Handler;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

/*
 * 立体視用に拡張したSurfaceViewクラス
 * 立体視有無の状態に応じて表示する画像を切り替える。
 * また、3D飛び出し設定情報に応じた描画処理を行う。
 */
public class SurfaceView3D extends SurfaceView implements
		SurfaceHolder.Callback {
	public int mPosX = 0, mPosY = 0; /* 画像の表示座標 */
	public int mVectorX = 10, mVectorY = 10; /* 画像の移動量 */
	public int mWidth = 0, mHeight = 0; /* 画面サイズ */
	private Context mContext; /* コンテキスト情報 */
	private SurfaceHolder mHolder; /* 描画制御用のSurfaceHolder */
	// private SurfaceController mSurfaceController = null; /* SurfaceView制御クラス
	// */
	// private Parallax mParallax; /* 視差情報取得用クラス */
	private final Handler mHandler = new Handler(); /* 描画用のハンドラー */
	private boolean mSidebyeSideFlg = false; /* 描画フォーマットの制御情報 */
	private Bitmap mImage = null, mImageHalf = null; /* 移動する画像データ */
	private Bitmap mBackImage = null, mBackImage3D = null; /* 背景画像データ */

	private Object handler = Reflector.load(getResources(), null);

	/*
	 * 描画用のスレッド
	 */
	private final Runnable drawThread = new Runnable() {
		public void run() {
			reDraw();
		}
	};

	/*
	 * コンストラクター SurfaceView制御用クラスを生成し、3D飛び出し設定情報を取得する。
	 * リソースから画像データを取得し、SidebySide(Half)用に横幅1/2の画像も生成する。
	 */
	public SurfaceView3D(Context context) {
		super(context);
		mContext = context;
		// mSurfaceController = new SurfaceController(this);
		// mParallax = new Parallax();
		getDepth();

		Resources res = context.getResources();
		mImage = BitmapFactory.decodeResource(res, R.drawable.android);
		mImageHalf = Bitmap.createScaledBitmap(mImage, mImage.getWidth() / 2,
				mImage.getHeight(), true);

		mHolder = getHolder();
		mHolder.addCallback(this);
	}

	/*
	 * Surfaceが生成されたときに呼ばれる。 描画処理を行う。
	 */
	public void surfaceCreated(SurfaceHolder holder) {
		Canvas mcanvas = null;

		mcanvas = mHolder.lockCanvas();
		stereoDraw(mcanvas);
		mHolder.unlockCanvasAndPost(mcanvas);
	}

	/*
	 * Surfaceの情報が変更されたときに呼ばれる。 画面サイズを更新する。 3D飛び出し設定情報を取得する。 描画処理を行う。
	 */
	public void surfaceChanged(SurfaceHolder holder, int format, int width,
			int height) {
		Canvas canvas = null;

		mWidth = width;
		mHeight = height;

		getDepth();

		canvas = mHolder.lockCanvas();
		stereoDraw(canvas);

		mHolder.unlockCanvasAndPost(canvas);
	}

	/*
	 * Surfaceが開放されたときに呼ばれる。 画像データを開放する。 描画用のスレッドを停止する。
	 */
	public void surfaceDestroyed(SurfaceHolder holder) {
		if (mImage != null) {
			mImage.recycle();
			mImage = null;
		}
		if (mImageHalf != null) {
			mImageHalf.recycle();
			mImageHalf = null;
		}
		if (mBackImage != null) {
			mBackImage.recycle();
			mBackImage = null;
		}
		if (mBackImage3D != null) {
			mBackImage3D.recycle();
			mBackImage3D = null;
		}
		mHandler.removeCallbacks(drawThread);
	}

	/*
	 * 描画処理を行う。 SidebySide(Half)を描画するかどうか判定を行う。
	 */
	private void stereoDraw(Canvas canvas) {
		drawBack(canvas);
		if (mSidebyeSideFlg == true) {
			draw3D(canvas);
		} else {
			draw2D(canvas);
		}
	}

	/*
	 * 背景画像を描画する。 必要に応じてリソースから画像データを取り出す。
	 */
	private void drawBack(Canvas canvas) {
		Rect dstRect = new Rect(0, 0, mWidth, mHeight);
		if (mSidebyeSideFlg == true) {
			if (mBackImage3D == null) {
				Resources res = mContext.getResources();
				mBackImage3D = BitmapFactory.decodeResource(res,
						R.drawable.welcome3d);
			}
			Rect srcRect = new Rect(0, 0, mBackImage3D.getWidth(),
					mBackImage3D.getHeight());
			canvas.drawBitmap(mBackImage3D, srcRect, dstRect, null);
		} else {
			if (mBackImage == null) {
				Resources res = mContext.getResources();
				mBackImage = BitmapFactory.decodeResource(res,
						R.drawable.welcome);
			}
			Rect srcRect = new Rect(0, 0, mBackImage.getWidth(),
					mBackImage.getHeight());
			canvas.drawBitmap(mBackImage, srcRect, dstRect, null);
		}
	}

	/*
	 * 立体視用にSidebySide(Half)のデータを描画する。 100msごとに描画するよう次回描画タイミングを設定する。
	 */
	private void draw3D(Canvas canvas) {

		mHandler.removeCallbacks(drawThread);
		mHandler.postDelayed(drawThread, 10);
	}

	/*
	 * 立体視ではないデータを描画する。 100msごとに描画するよう次回描画タイミングを設定する。
	 */
	private void draw2D(Canvas canvas) {
		Reflector.next(handler, canvas);

		mHandler.removeCallbacks(drawThread);
		mHandler.postDelayed(drawThread, Reflector.nextTime(handler));
	}

	/*
	 * 3D飛び出し設定情報を取得する
	 */
	private void getDepth() {
		// mDepthF = mParallax.get3dDepthSettingsFl(); /* ★Addon用API使用箇所★ */
	}

	public void onPause() {
	}

	/*
	 * アプリケーションが再開されるときに呼ばれる。 3D飛び出し設定情報を取得する
	 */
	public void onResume() {
		getDepth();
	}

	/*
	 * 再描画する
	 */
	public void reDraw() {
		Canvas canvas = null;
		canvas = mHolder.lockCanvas();
		if (canvas == null)
			return;

		stereoDraw(canvas);
		mHolder.unlockCanvasAndPost(canvas);
	}

	/*
	 * 立体視有無の制御を行う。
	 * 
	 * @param　　mode trueの場合は立体視有り。falseは立体視無し。
	 */
	void setStereoMode(boolean mode) {
		mSidebyeSideFlg = mode;
		// mSurfaceController.setStereoView(mode); /* ★Addon用API使用箇所★ */
	}
}
